package com.tbit.uqbike.webmanager.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.common.utils.TraceUtil;
import com.tbit.uqbike.annos.OperateLog;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.*;
import com.tbit.uqbike.object.pojo.dto.BatchRegisterAuthDTO;
import com.tbit.uqbike.object.pojo.vo.UserFaceDataVO;
import com.tbit.uqbike.object.pojo.vo.UserVO;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.base.MachineService;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.service.rpcservice.MachineBorrowService;
import com.tbit.uqbike.webmanager.dao.core.UserToAgentDao;
import com.tbit.uqbike.webmanager.util.Assert;
import com.tbit.uqbike.webmanager.util.ExportExcelUtils;
import com.tbit.uqbike.webmanager.util.ServletUtils;
import com.tbit.uqbike.webmanager.util.excel.ExportExcelUtil;
import com.tbit.uqbike.webmanager.util.excel.ExportExcelWrapper;
import com.tbit.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.ws.rs.FormParam;
import java.io.IOException;
import java.util.*;

/**
 * @author chenmengran
 * @Description: 用户管理
 * @date 2019\12\16 001615:28
 */
@Slf4j
@Validated
@RestController
@RequestMapping(value = "/user", produces = BaseController.MEDIA_JSON_UTF8)
public class UserController extends BaseController {
    @Autowired
    private AccountService accountService;
    @Autowired
    private UserService userService;
    @Autowired
    private SmsLogService smsLogService;
    @Autowired
    private UserAccountLogService userAccountLogService;
    @Autowired
    private GiftCardUserService giftCardUserService;
    @Autowired
    private MachineService machineService;
    @Autowired
    private MachineBorrowService machineBorrowService;
    @Autowired
    private UserFaceDataService userFaceDataService;
    @Autowired
    private AccountConfigExtService accountConfigExtService;
    @Autowired
    private UserToAgentDao userToAgentDao;
    @Autowired
    private OperaPswService operaPswService;

    /* 分页查询 */
    @RequestMapping("/queryPage")
    public JsonResult queryPage(String name, String idNo, Integer draw, String userCode,
                                @RequestParam(defaultValue = "10") Integer rowCount,
                                @RequestParam(defaultValue = "1") Integer pageNO, String phone,
                                HttpServletRequest request, Integer nameAuth, Integer depositState, Long startTime, Long endTime) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (userCode != null) {
            Machine machine = machineService.getByUserCode(userCode);
            if (machine != null) {
                MachineBorrow machineBorrow = machineBorrowService.getByMachineId(machine.getMachineId());
                if (machineBorrow != null) {
                    phone = userService.getByUserId(machineBorrow.getUserId()).getPhone();
                }
            } else {
                throw new BaseException(SystemCodeEnum.MACHINE_NOT_EXIST);
            }
        }
        //查询总数
        Integer total = userService.queryCount(loginInfo, phone, name, idNo, nameAuth, depositState, startTime, endTime);
        //查询具体用户
        List<User> users = userService.queryPage(loginInfo, phone, name, idNo, rowCount, pageNO, nameAuth, depositState, startTime, endTime);
        //用户基本信息脱敏
        users.forEach(User::desensitization);
        return JsonResult.ok(users, total);
    }

    /* 查询发送验证码*/
    @RequestMapping("/getAuthCode")
    public JsonResult getAuthCode(Integer accountId,
                                  @NotNull(message = "ver.phone.notNull") String phone,
                                  HttpServletRequest request) {
        /* 校验 */
        LoginInfo loginInfo = getLogin(request);
        if (loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            Assert.notNull(accountId, "ver.accountId.notNull");
            Account account = accountService.getById(accountId);
            accountId = account.getAccountId();
        } else if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            accountId = loginInfo.id;
        } else {
            Account account = accountService.getById(loginInfo.id);
            accountId = account.getParentId();
        }
        SmsLog smsLog = null;
        List<SmsLog> smsLogs = smsLogService.findByphone(accountId, phone);
        if (smsLogs.size() > 0) {
            smsLog = smsLogs.get(0);
        }
        return JsonResult.ok(smsLog);
    }

    /* 冻结押金 */
    @RequestMapping("/frozenDeposit")
    @OperateLog(module = ModuleEnum.USER, methods = MethodEnum.USER_FROZENDEPOSIT)
    public JsonResult frozenDeposit(@NotNull(message = "ver.userId.notNull") Integer userId,
                                    @NotNull(message = "ver.depositState.notNull") Integer depositState,
                                    HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_BRAND)
                && !loginInfo.type.equals(UserConstant.USER_ADMIN)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        //验证
        User user = userService.getByUserId(userId);
        if (loginInfo.type.equals(UserConstant.USER_BRAND)) {
            if (!user.getAccountId().equals(loginInfo.id)) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }
        userService.frozenDeposit(userId, depositState);

        return JsonResult.ok();
    }

    /* 更新用户礼品卡金额 */
    @RequestMapping("/updateMoney")
    @OperateLog(module = ModuleEnum.USER, methods = MethodEnum.USER_EDITGIFRMONEY)
    public JsonResult updateMoney(@NotNull(message = "ver.accountId.notNull") Integer accountId,
                                  @NotNull(message = "ver.userId.notNull") Integer userId,
                                  @NotNull(message = "ver.type.notNull") Integer type,
                                  @NotNull(message = "ver.money.notNull") Integer money,
                                  @NotNull(message = "ver.secret.notNull") String secret,
                                  @NotNull(message = "ver.remark.notNull") String remark,
                                  HttpServletRequest request) {
        if (true) {
            //前端没看到有调用这个接口，弃用，防止调用产生脏数据
            return JsonResult.fail("接口已弃用", TraceUtil.getTraceIdByLocal());
        }
        //if (!OperaPswConstant.USER_OPERA_UPDATE_MONEY.equals(secret)) {
        //    throw new BaseException(SystemCodeEnum.SUPER_CODE_ERROR);
        //}
        if (type != 0 && type != 1) {
            throw new BaseException(SystemCodeEnum.OPERATE_TYPE_ERROR);
        }
        LoginInfo info = getLogin(request);
        //权限
        if (!info.type.equals(UserConstant.USER_ADMIN)
                && !info.type.equals(UserConstant.USER_BRAND)) {
            throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
        }
        User user = userService.getByUserId(userId);
        if (user == null) {
            throw new BaseException(SystemCodeEnum.USER_NOT_EXIST);
        }
        if (info.type.equals(UserConstant.USER_BRAND)) {
            if (!info.id.equals(user.getAccountId())) {
                throw new BaseException(SystemCodeEnum.NO_PRIVILEGE);
            }
        }
        /**添加变动日志*/
        UserAccountLog userAccountLog = new UserAccountLog();
        userAccountLog.setAccountId(user.getAccountId());
        userAccountLog.setUserId(user.getUserId());
        userAccountLog.setMoneyType(0);//moneytype=0代表个人余额，1代表礼品卡余额
        userAccountLog.setType(type);//type=0代表扣款，1代表充值
        userAccountLog.setMoney(money);
        userAccountLog.setOperaTime(new Date());
        if (type == 0) {
            userAccountLog.setRemark("系统人工扣费,备注=" + remark);
            money = -money;
        } else if (type == 1) {
            userAccountLog.setRemark("系统人工充值,备注=" + remark);
        }
        userAccountLogService.insert(userAccountLog);
        /**修改礼品卡金额*/
        giftCardUserService.updateMoney(accountId, userId, money);
        return JsonResult.ok();
    }

    /* 实名认证 */
    @RequestMapping("/nameAuth")
    public JsonResult nameAuth(@NotNull(message = "ver.accountId.notNull") Integer accountId,
                               @NotNull(message = "ver.userId.notNull") Integer userId,
                               @NotNull(message = "ver.idNO.notNull") String idNO,
                               @NotNull(message = "ver.name.notNull") String name,
                               HttpServletRequest request) {
        userService.updateNameAuth(userId, name, idNO ,BaseController.getLogin(request));
        return JsonResult.ok();
    }

    /* 学生认证 */
    @RequestMapping("/studentAuth")
    public JsonResult studentAuth(@NotNull(message = "ver.userId.notNull") Integer userId,
                                  @NotNull(message = "ver.studentIdNO.notNull") String studentIdNO, HttpServletResponse response) {

        userService.updateStudentAuth(userId, 1, studentIdNO);

        return JsonResult.ok();
    }

    /* 查询用户费用 */
    @RequestMapping("/getUserFee")
    public JsonResult getUserFee(@NotNull(message = "ver.phone.notNull") String phone, HttpServletResponse response, HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        Long money = userService.getUserFee(phone, loginInfo);

        return JsonResult.ok(money);
    }


    /**
     * @param userId
     * @param money
     * @param remark
     * @param operaPsw
     * @return com.tbit.uqbike.object.view.JsonResult
     * @Description: 余额修改
     * @createDate 2020/11/20 14:32
     */
    @RequestMapping("/recharge")
    @OperateLog(module = ModuleEnum.USER, methods = MethodEnum.USER_EDITMONEY)
    public JsonResult recharge(Integer userId, Integer money, String remark, String operaPsw, HttpServletRequest request) {
        Assert.notNull(userId, "ver.userId.notNull");
        Assert.notNull(money, "money_not_null");
        Assert.hasLength(remark, "remark_not_null");
        // 金额不能等于
        if (money == 0) {
            throw new BaseException("money_not_zero");
        }
        if (remark.length() > 200){
            return JsonResult.fail("备注不能超过200个字符", TraceUtil.getTraceIdByLocal());
        }
        /**操作密码校验*/
        operaPswService.checkOperaPsw(BaseController.getLogin(request), OperaPswEnum.OPERA_PSW_MONEY_CONFIG.getModule(), operaPsw);

        userService.recharge(userId, money, remark, getLogin(request));
        return JsonResult.ok();
    }

    /* 清空实名认证信息 */
    @RequestMapping("/editNameAuth")
    public JsonResult editNameAuth(@NotNull(message = "ver.userId.notNull") Integer userId) {
        userService.editNameAuth(userId);
        // 当前区域实名认证类型是 身份证+人脸识别 删除本地人脸缓存
        UserToAgent userToAgent = userToAgentDao.getByUserId(userId);
        if(Objects.nonNull(userToAgent)){
            AccountConfigExt nameAuthType = accountConfigExtService.getByAccountIdAndType(userToAgent.getAccountId(), "nameAuthType");
            if (Objects.nonNull(nameAuthType) && Objects.equals("2",nameAuthType.getParamValue())){
                userFaceDataService.remove(new LambdaQueryWrapper<UserFaceDataVO>().eq(UserFaceDataVO::getUserId,userId));
            }
        }
        return JsonResult.ok();
    }

    /**
     * 修改用户手机号码
     */
    @RequestMapping("/updatePhone")
    public JsonResult edit(@NotNull(message = "ver.userId.notNull") Integer userId, @NotNull(message = "ver.phone.notNull") String phone,
                           @NotNull(message = "reson_not_null") String reson) {
        LoginInfo login = getLogin(ServletUtils.getRequest());
        Integer operaUserId = login.getAccountUserId();
        return JsonResult.toAjax(userService.updateUser(userId, phone, operaUserId, reson, login), login.context);
    }

    @GetMapping("/export")
    public JsonResult export(User user, HttpServletRequest request) throws IOException, ServletException {
        /**操作密码校验*/
        operaPswService.checkOperaPsw(BaseController.getLogin(request), OperaPswEnum.OPERA_PSW_OPERATION_CONFIG.getModule(), user.getOperaPsw());

        boolean exportBrandName = getLogin(request).type.equals(UserConstant.USER_ADMIN);
        return JsonResult.ok(userService.batchExport(user, exportBrandName, "用户数据"));
    }

    @PostMapping("/addRemark")
    public Result<String> addUserRemark(@NotNull(message = "ver.userId.notNull") @FormParam("userId") Integer userId, @FormParam("remark") String remark) {
        int maxLength = 255;
        if (StringUtils.isNotBlank(remark) && remark.length() > maxLength) {
            return Result.error("备注过长,只能添加255个汉字");
        }
        userService.addUserRemark(userId, remark);
        return Result.success();
    }

    /**
     * 清空实名认证提交次数
     *
     * @param userId
     * @return
     */
    @RequestMapping("/editNameAuthCount")
    public Result editNameAuthCount(@NotNull(message = "ver.userId.notNull") Integer userId) {
        userService.editNameAuthCount(userId);
        return Result.success();
    }

    /**
     * 批量注册认证用户
     * @param brandId
     * @param file
     * @param request
     * @param override 是否覆盖已存在用户，0/1
     * @return
     */
    @OperateLog(module = ModuleEnum.USER, methods = MethodEnum.USER_IMPORT_AUTH)
    @RequestMapping("/batchRegisterAuth")
    public Result batchRegisterAuth(@NotNull(message = "ver.accountId.notNull") Integer brandId, @RequestParam("file") MultipartFile[] file,
                                    HttpServletRequest request, Integer override){
        LoginInfo loginInfo = getLogin(request);
        Integer accountUserId = loginInfo.getAccountUserId();
        List<BatchRegisterAuthDTO> info = getInfo(file, 1000, brandId, accountUserId, loginInfo);
        if(CollectionUtils.isEmpty(info)){
            return Result.success();
        }
        if(info.size() > 1000){
            throw new BaseException(SystemCodeEnum.AUTH_UPLOAD_SIZE_LIMIT);
        }
        if(override == null){
            override = 0;
        }
        userService.batchRegisterAuth(info, override,loginInfo);
        return Result.success();
    }
    /**
     * 批量注册认证用户，返回逗号隔开的重复手机号
     * @param brandId
     * @param file
     * @param request
     * @return
     */
    @RequestMapping("/batchRegisterAuthCheck")
    public Result batchRegisterAuthCheck(@NotNull(message = "ver.accountId.notNull") Integer brandId, @RequestParam("file") MultipartFile[] file,
                                    HttpServletRequest request){
        LoginInfo loginInfo = getLogin(request);
        Integer accountUserId = loginInfo.getAccountUserId();
        List<BatchRegisterAuthDTO> info = getInfo(file, 1000, brandId, accountUserId, loginInfo);
        if(CollectionUtils.isEmpty(info)){
            return Result.success();
        }
        if(info.size() > 1000){
            throw new BaseException(SystemCodeEnum.AUTH_UPLOAD_SIZE_LIMIT);
        }
        String s = userService.batchRegisterAuthCheck(info);
        return Result.success(s);
    }

    /**
     * 导出模板
     * @param request
     * @param response
     */
    @RequestMapping(value = "/batchRegisterAuthTemplate")
    public void exportTemplate(HttpServletRequest request, HttpServletResponse response) {
        // 下载模板文件
        LoginInfo info = getLogin(request);
        String phone = info.context.getMessage("user.template.phone");
        String name = info.context.getMessage("user.template.name");
        String idNo = info.context.getMessage("user.template.idno");
        String authNo = info.context.getMessage("user.template.authno");
        List<String[]> listContent = new LinkedList<>();
        String[] headers = {phone, name, idNo, authNo};
        listContent.add(headers);
        String[] items = new String[]{"123456789", "张三", "131354654654", "646546"};
        listContent.add(items);
        ExportExcelWrapper<String[]> export = new ExportExcelWrapper<>();
        export.exportExcel("template", "template", null, listContent, response, ExportExcelUtil.EXCEL_FILE_2003);
    }

    /**
     * 根据用户id获取用户信息
     * @param userId 用户id
     * @return 用户信息详情
     */
    @GetMapping("/getByUserId")
    public Result<User> getByUserId(Integer userId) {
        return Result.success(userService.getByUserId(userId));
    }

    /**
     * 查询用户看板
     *
     * @param userId     用户id
     * @param accountIds 区域id逗号拼接
     */
    @GetMapping("/getInfoByUserId")
    public Result<UserVO> getInfoByUserId(@NotNull Integer userId,@NotBlank String accountIds) {
        UserVO userVO = userService.getInfoByUserId(userId, accountIds);
        return Result.success(userVO);
    }

    public List<BatchRegisterAuthDTO> getInfo(MultipartFile[] files, Integer type, Integer brandId, Integer accountUserId, LoginInfo loginInfo) {
        if (null == files || files.length == 0) {
            throw new BaseException(SystemCodeEnum.HAVE_NOT_FILE);
        }
        List<List<String>> data = null;
        try {
            data = ExportExcelUtils.readExcelDataFirst(files[0].getBytes(), type);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
        if (null == data) {
            throw new BaseException(SystemCodeEnum.READ_FILE_ERROR);
        }
        List<BatchRegisterAuthDTO> list = new ArrayList<>();
        for (List<String> datum : data) {
            String phone = datum.get(0);
            if (!phone.matches("^1[0-9]{10}$")) {
                throw new BaseException(SystemCodeEnum.PHONE_NOT_VALID);
            }
            String name = datum.get(1);
            String idNo = datum.get(2);
            String authNo = datum.get(3);
            if(!org.springframework.util.StringUtils.hasLength(phone)){
                throw new BaseException(SystemCodeEnum.PHONE_NOT_NULL);
            }
            BatchRegisterAuthDTO batchRegisterAuthDTO = new BatchRegisterAuthDTO();
            batchRegisterAuthDTO.setPhone(phone);
            batchRegisterAuthDTO.setName(name);
            batchRegisterAuthDTO.setIdNo(org.springframework.util.StringUtils.hasLength(idNo) ? idNo : null);
            batchRegisterAuthDTO.setAuthNo(org.springframework.util.StringUtils.hasLength(authNo) ? authNo : null);
            batchRegisterAuthDTO.setBrandId(brandId);
            batchRegisterAuthDTO.setAccountUserId(accountUserId);
            batchRegisterAuthDTO.setStudentAuth(0);
            batchRegisterAuthDTO.setNameAuth(0);
            if(org.springframework.util.StringUtils.hasLength(batchRegisterAuthDTO.getAuthNo())){
                batchRegisterAuthDTO.setStudentAuth(1);
            }
            if(org.springframework.util.StringUtils.hasLength(batchRegisterAuthDTO.getIdNo())){
                batchRegisterAuthDTO.setNameAuth(1);
            }
            batchRegisterAuthDTO.setRemark(loginInfo.getName() + "批量导入");
            batchRegisterAuthDTO.setCountry(86);
            batchRegisterAuthDTO.setJoinTime(DateTimeUtil.getNowTime());
            batchRegisterAuthDTO.setUpdateTime(DateTimeUtil.getNowTime());
            list.add(batchRegisterAuthDTO);
        }
        if (CollectionUtils.isEmpty(list)) {
            throw new BaseException(SystemCodeEnum.COLL_IS_EMPTY);
        }
        return list;
    }

}
